import AttendanceRecord, { ClockInResult, ClockOutResult } from "./AttendanceRecord";
import Department from "./Department";
import Machine from "./Machine";
import Worker from "./Worker";
import { Moment } from 'moment';
import UndefinedWorker from "./UndefinededWorker";
import { v4 as uuid } from 'uuid';

export interface AttendanceRecordItemModel {
    worker: Worker;
    attendanceRecordList: AttendanceRecord[];
}

export interface AttendanceRecordModel {
    attendanceRecordItemModelList: AttendanceRecordItemModel[];
    startDate: Moment | null;
    endDate: Moment | null;
    isValid: boolean;
    undefinedWorkerList: UndefinedWorker[];
}

export let machineMap: Map<string, Machine> = new Map();
export let departmentMap: Map<string, Department> = new Map();
export let workerMap: Map<string, Worker> = new Map();
export let officialHolidays: number = 4;
export let attendanceRecordModel: AttendanceRecordModel = {
    attendanceRecordItemModelList: [],
    startDate: null,
    endDate: null,
    isValid: false,
    undefinedWorkerList: []
};

export function forcedAlignment() {
    const { attendanceRecordItemModelList, startDate, endDate } = attendanceRecordModel;
    attendanceRecordItemModelList.forEach((AttendanceRecordItemModel) => {
        const { attendanceRecordList } = AttendanceRecordItemModel;
        const recordNum = attendanceRecordList.length;
        let totalDays = 0;
        if (endDate !== null && startDate != null) {
            totalDays = endDate.diff(startDate, 'days') + 1;
        }
        if (recordNum < totalDays) {
            const firstRecord = attendanceRecordList[0];
            for (let i = 0, limit = totalDays - recordNum; i < limit; i++) {
                attendanceRecordList.push(new AttendanceRecord({
                    id: uuid(),
                    date: firstRecord.date,
                    worker: firstRecord.worker,
                    origin: '',
                    clockInfo: {
                        clockInInfo: {
                            clockInMoment: null,
                            clockInResult: ClockInResult.ABSENTEEISM_LATE
                        },
                        clockOutInfo: {
                            clockOutMoment: null,
                            clockOutResult: ClockOutResult.ABSENTEEISM_EARLY
                        }
                    },
                    clockMomentList: []
                }));
            }
        } else if (recordNum > totalDays) {
            AttendanceRecordItemModel.attendanceRecordList = attendanceRecordList.slice(0, totalDays);
        }
    });
}

export function resetStore() {
    machineMap = new Map();
    departmentMap = new Map();
    workerMap = new Map();
    officialHolidays = 4;
    attendanceRecordModel = {
        attendanceRecordItemModelList: [],
        startDate: null,
        endDate: null,
        isValid: false,
        undefinedWorkerList: []
    };
}

export function addAttendanceRecordItemModel(attendanceRecordItemModel: AttendanceRecordItemModel) {
    attendanceRecordModel.attendanceRecordItemModelList.push(attendanceRecordItemModel);
}

export function addUndefinedWorker(undefinedWorker: UndefinedWorker) {
    attendanceRecordModel.undefinedWorkerList.push(undefinedWorker);
}

export function setStartDate(startDate: Moment | null) {
    if (startDate !== null) {
        attendanceRecordModel.startDate = startDate;
    }
}

export function refreshIsValidStatus() {
    const { attendanceRecordItemModelList, startDate, endDate } = attendanceRecordModel;
    attendanceRecordModel.isValid = attendanceRecordItemModelList.length > 0 && startDate !== null && endDate !== null;
}

export function setEndDate(endDate: Moment | null) {
    if (endDate !== null) {
        attendanceRecordModel.endDate = endDate;
    }
}

export function replaceAttendanceRecordModel(tempAttendanceRecordModel: AttendanceRecordModel) {
    attendanceRecordModel = tempAttendanceRecordModel;
}

export function setOfficialHolidays(num: number): void {
    if (num >= 0) {
        officialHolidays = num;
    }
}

export function addMachine(machine: Machine): Map<string, Machine> {
    machineMap.set(machine.id, machine);
    return machineMap;
}

export function addDepartment(department: Department): Map<string, Department> {
    departmentMap.set(department.id, department);
    return departmentMap;
}

export function addWorker(worker: Worker): Map<string, Worker> {
    workerMap.set(`${worker.machine.id}-${worker.id}`, worker);
    return workerMap;
}

export function getMachine(id: string) {
    return machineMap.get(id);
}

export function getDepartment(id: string) {
    return departmentMap.get(id);
}

export function getWorker(machineId: string, id: string) {
    return workerMap.get(`${machineId}-${id}`);
}